package cn.tpshion.vm.handler.task;

import cn.tpshion.vm.common.constant.MsgType;
import cn.tpshion.vm.common.constant.NodeType;
import cn.tpshion.vm.common.constant.SecretType;
import cn.tpshion.vm.domain.entity.Secret;
import cn.tpshion.vm.domain.entity.TaskHis;
import cn.tpshion.vm.domain.entity.table.TaskHisTableDef;
import cn.tpshion.vm.domain.support.GitData;
import cn.tpshion.vm.domain.support.MsgData;
import cn.tpshion.vm.domain.support.NodeContext;
import cn.tpshion.vm.handler.task.support.AbstractNodeHandler;
import cn.tpshion.vm.handler.task.support.MsgProgressMonitor;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.eclipse.jgit.api.CreateBranchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.util.List;

@Slf4j
@Component
public class GitHandler extends AbstractNodeHandler<GitData> {

    @Override
    public NodeType getNodeType() {
        return NodeType.GIT;
    }

    @Override
    protected void handleNode(NodeContext context) throws Exception {
        GitData data = getData(context);
        Secret secret = getSecret(SecretType.GIT.getType(), data.getSecretName());
        UsernamePasswordCredentialsProvider credentials = new UsernamePasswordCredentialsProvider(secret.getSecretKey(), secret.getSecretValue());

        String uri = data.getUrl();
        String name = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf("."));
        String branch = StringUtils.hasText(data.getBranch()) ? data.getBranch() : data.getDefaultBranch();

        sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "项目地址：" + data.getUrl()));
        sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "执行git分支：" + branch));

        File file = new File(nodeConfig.getWorkspace() + File.separator + context.getTaskId() + File.separator + name);
        String commitVersion = null;
        String commitMsg = null;
        if(file.exists() && file.isDirectory()){

            try (Git git = new Git(new FileRepository(file.getPath() + "/.git"))) {
                ListBranchCommand branchList = git.branchList();
                List<Ref> refList = branchList.call();
                boolean createBranch = true;
                for (Ref ref : refList) {
                    log.info("getBranchList branch: {} name: {}", ref.getName(), ref.getObjectId().getName());
                    if(StringUtils.startsWithIgnoreCase(ref.getName(), "refs/heads/" + branch)){
                        createBranch = false;
                        break;
                    }
                }

                git.checkout()
                        .setName(branch)
                        .setProgressMonitor(new MsgProgressMonitor(context, sseHandle))
                        .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.SET_UPSTREAM)
                        .setStartPoint("origin/" + branch)
                        .setForced(true)
                        .setCreateBranch(createBranch)
                        .call();

                git.pull()
                        .setProgressMonitor(new MsgProgressMonitor(context, sseHandle))
                        .setCredentialsProvider(credentials)
                        .call();

                log.info("仓库地址:{}", git.getRepository().getDirectory());
                sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "仓库地址：" + git.getRepository().getDirectory()));

                Iterable<RevCommit> commits = git.log().call();
                for (RevCommit commit : commits) {
                    commitVersion = commit.getName();
                    commitMsg = commit.getShortMessage();

                    log.info("提交版本号：{} 提交信息：{}", commitVersion, commitMsg);
                    sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "提交版本号：" + commit.getName() + " 提交信息：" + commit.getShortMessage()));
                    break;
                }
            }
        }else{
            FileUtils.deleteDirectory(file);
            try (Git git = Git.cloneRepository()
                    .setURI(data.getUrl())
                    .setBranch(branch)
                    .setDirectory(file)
                    .setCredentialsProvider(credentials)
                    .call()) {

                log.info("仓库地址:{}", git.getRepository().getDirectory());
                sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "仓库地址：" + git.getRepository().getDirectory()));

                Iterable<RevCommit> commits = git.log().call();
                for (RevCommit commit : commits) {
                    commitVersion = commit.getName();
                    commitMsg = commit.getShortMessage();

                    log.info("提交版本号：{} 提交信息：{}", commitVersion, commitMsg);
                    sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "提交版本号：" + commit.getName() + " 提交信息：" + commit.getShortMessage()));
                    break;
                }
            }
        }
        context.setWorkspace(file.getAbsolutePath());

        TaskHis taskHis = new TaskHis();
        taskHis.setGitMsg(commitMsg);
        taskHis.setGitBranch(branch);

        QueryWrapper queryWrapper = QueryWrapper.create().where(
                TaskHisTableDef.TASK_HIS.BATCH_ID.eq(context.getBatchId())
                        .and(TaskHisTableDef.TASK_HIS.TASK_ID.eq(context.getTaskId()))
        );
        taskHisMapper.updateByQuery(taskHis, true, queryWrapper);
    }
}
